package com.ftg.learn.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ftg.learn.dto.ModifyBuyNumInCartDto;
import com.ftg.learn.entity.ProdEntity;
import com.ftg.learn.service.CartService;
import com.ftg.learn.service.ProdService;
import com.ftg.learn.util.R;
import com.ftg.learn.util.TipUtil;
import com.ftg.learn.vo.ProdRedisVo;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 布衣
 */
@Service
public class CartServiceImpl implements CartService {

    //前置
    private final String cartKeyValuePrefix = "cart_";

    @Resource
    StringRedisTemplate stringRedisTemplate;

    @Resource
    ProdService prodService;

    @Resource
    ObjectMapper objectMapper;

    @Override
    public R<String> addToCart(String userId, String prodId) {
        if (StringUtils.isEmpty(userId)) {
            return R.build(TipUtil.TOKEN_ANALYZE_ERR_NOLOGIN);
        }
        //先查询商品信息
        ProdRedisVo byId = prodService.getById(Long.valueOf(prodId));
        //向redis添加一个key,商品value
        List<ProdRedisVo> prods = Collections.singletonList(byId);
        String cartVal = stringRedisTemplate.opsForValue().get(cartKeyValuePrefix + userId);
        if (StringUtils.isEmpty(cartVal)) {

            if (StringUtils.isEmpty(prodId)) {
                return R.build(TipUtil.CART_ERROR_PRODUCT_NOT_EXIST);
            }

            //byid里面的总库存是否大于当前购买量

            try {
                stringRedisTemplate.opsForValue().set(cartKeyValuePrefix + userId, objectMapper.writeValueAsString(prods));
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
            return R.build(TipUtil.CART_SUCCESS_ADD_PRODUCT);
        } else {
            //反序列化成为一个类.  json ->list<商品信息>
            //对原有同id 商品添加数量
            try {
                List<ProdRedisVo> list = objectMapper.readValue(cartVal, new TypeReference<List<ProdRedisVo>>() {
                });
                boolean ist = false;
                for (int i = 0, len = list.size() - 1; i <= len; i++, len--) {
                    ProdRedisVo leftVo = list.get(i);
                    if (leftVo.getProdId().equals(byId.getProdId())) {
                        leftVo.setBuyNum(leftVo.getBuyNum() + 1);
                        ist = true;
                        break;
                    }
                    ProdRedisVo rightVo = list.get(len);
                    if (rightVo.getProdId().equals(byId.getProdId())) {
                        rightVo.setBuyNum(rightVo.getBuyNum() + 1);
                        ist = true;
                        break;
                    }
                }

                if (!ist) {
                    list.add(byId);
                }
                stringRedisTemplate.opsForValue().set(cartKeyValuePrefix + userId, objectMapper.writeValueAsString(list));
                return R.build(TipUtil.CART_SUCCESS_ADD_PRODUCT);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public R<String> getDataFormRedis(String userId) {
        String cartVal = stringRedisTemplate.opsForValue().get(cartKeyValuePrefix + userId);
        return R.build(TipUtil.CART_SUCCESS_LIST, cartVal);
    }

    @Override
    public R<String> update(String userId,ModifyBuyNumInCartDto buyNumDto) {

        List<ProdRedisVo> prodRedisVos = this.castCartToProdRedisVo(Long.valueOf(userId));
        //找到对应的商品对数量进行修改
        for (ProdRedisVo prodRedisVo : prodRedisVos) {
            if (prodRedisVo.getProdId().equals(buyNumDto.getProdId())) {
                prodRedisVo.setBuyNum(buyNumDto.getBuyNum());
                break;
            }
        }
        // 覆盖redis数据
        try {
            stringRedisTemplate.opsForValue().set(cartKeyValuePrefix + userId, objectMapper.writeValueAsString(prodRedisVos));
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return R.build(TipUtil.CART_SUCCESS_UPDATE);
    }

    @Override
    public R<String> deleteByProId(Long userId, Long prodId) {

        List<ProdRedisVo> prodRedisVos = this.castCartToProdRedisVo(userId);

        //stream
        List<ProdRedisVo> collect = prodRedisVos.stream()
                .filter(x -> !x.getProdId().equals(prodId))
                .collect(Collectors.toList());

        try {
            String prods = objectMapper.writeValueAsString(collect);
            stringRedisTemplate.opsForValue().set(cartKeyValuePrefix + userId, prods);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return R.build(TipUtil.CART_SUCCESS_DELETE);
    }

    @Override
    public R<String> deleteAll(String userId) {
        //删除redis里面原key
        stringRedisTemplate.delete(cartKeyValuePrefix + userId);
        return R.build(TipUtil.CART_SUCCESS_CLEAR_ALL);
    }

    /**
     * 获取购物车
     *
     * @param userId 用户编号
     * @return String
     */
    private String getCartFromRedis(Long userId) {
        return stringRedisTemplate.opsForValue().get(cartKeyValuePrefix + userId);
    }

    /**
     * 将购物车数据转换为ProdRedisVo
     *
     * @param userId 用户编号
     * @return List<ProdRedisVo>
     */
    private List<ProdRedisVo> castCartToProdRedisVo(Long userId) {
        List<ProdRedisVo> list = null;
        try {
            list = objectMapper.readValue(this.getCartFromRedis(userId), new TypeReference<List<ProdRedisVo>>() {
            });
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return list;
    }

}
